#include "Camera.h"
#include "Vector3.h"
#include "Player.h"
#include "BMPLoader.h"
#include <iostream>
#include <GL/glut.h>
#include <cmath>

float rotationAngle = 0;

void Camera::initializeBackground()
{
	BMPClass bmp;
	BMPLoad("stars.bmp",bmp);
	
	
	glGenTextures(1, &skyTexture);
	glBindTexture(GL_TEXTURE_2D, skyTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	//reapeat
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);	//repeate
	
	glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes);
	
	
	BMPClass bmp2;

	BMPLoad("mars.bmp",bmp2);

	glGenTextures(1, &planetTexture);
	glBindTexture(GL_TEXTURE_2D, planetTexture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);	//reapeat
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);	//repeate
	
	glTexImage2D(GL_TEXTURE_2D,0,3,bmp2.width,bmp2.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp2.bytes);


	sphere = gluNewQuadric();
	gluQuadricTexture(sphere, GL_TRUE);
	gluQuadricOrientation(sphere, GLU_OUTSIDE);
}

void Camera::drawSky()
{
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();

	glEnable(GL_TEXTURE_2D);
	//glEnable(GL_BLEND);
	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);

	//glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glTexEnvi(GL_TEXTURE_ENV, 
			GL_TEXTURE_ENV_MODE, GL_DECAL); 
	
	
	glBindTexture(GL_TEXTURE_2D, skyTexture);
	
	
	gluQuadricTexture(sphere, GL_TRUE);

	// To fix "dull" sky
	gluQuadricOrientation(sphere, GLU_INSIDE);

	glTranslatef(lookFrom.x, lookFrom.y, lookFrom.z - 300);
	glRotatef(45,0,0,1);
	glRotatef(rotationAngle,0,1,0);
	glRotatef(90,1,0,0);
	gluSphere(sphere,500,50,50);
	glPopMatrix();
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);

	glTexEnvi(GL_TEXTURE_ENV, 
			GL_TEXTURE_ENV_MODE, GL_DECAL);
	glPushMatrix();
	glTranslatef(lookFrom.x - 150, lookFrom.y - 180, lookFrom.z - 300);
	glRotatef(45,0,0,1);
	glRotatef(rotationAngle,0,1,0);
	glRotatef(-90,1,0,0);
		

	glBindTexture(GL_TEXTURE_2D, planetTexture);
	
	gluQuadricOrientation(sphere, GLU_OUTSIDE);
	gluSphere(sphere,180,50,50); //planet

	//gluQuadricTexture(sphere,GL_FALSE);
	//gluQuadricDrawStyle(sphere,GLU_SILHOUETTE);
	//gluSphere(sphere,200,50,50);	//atmos
	//gluQuadricTexture(sphere,GL_TRUE);



	
	//gluSphere(sphere,100,50,50);
	
	
	//glDisable(GL_BLEND);
	glDisable(GL_TEXTURE_2D);
	glPopMatrix();
	
}

Camera::Camera():lookFrom(0,0,1), lookAt(0,0,0), viewUp(0,1,0), fov(45){

	initializeBackground();
}

Camera::Camera(Vector3 lf, Vector3 la, Vector3 vup, float FOV): lookFrom(lf), lookAt(la), viewUp(vup), fov(FOV){
	initializeBackground();
}

void Camera::update(Player& player)
{
	if (rotationAngle < 360)
	{
		rotationAngle += 0.05;
	}else{
		rotationAngle = 0;
	}
	
	// KEY IDEA:
	// camera moves same velocity as player, but moves an additional amount if player is not in right spot.
	// This also DEPENDS ON DIRECTION OF MOVEMENT!
	const Vector3& pos = player.getPos();
	

	//double xDist = cos(((double)4 / 3) * fov) * (lookFrom.getMagnitude());

	float camXvel = player.xVel;
	if (camXvel < 0)
	{
		if ( (pos.x - lookAt.x) < xLeadAmt )
			camXvel -= 6;

	}else if (camXvel > 0)
	{
		if ( (lookAt.x - pos.x) < xLeadAmt )
			camXvel += 6;
	}

	lookAt.x += camXvel;
	lookAt.y += player.yVel;	// keep centered in y direction

	lookFrom.x += camXvel;
	lookFrom.y += player.yVel;	// centered

	// Set up camera
	glMatrixMode(GL_MODELVIEW); 
	glLoadIdentity(); 
	gluLookAt(lookFrom.x, lookFrom.y, lookFrom.z,
		      lookAt.x, lookAt.y, lookAt.z,
			  viewUp.x, viewUp.y, viewUp.z);
}

Vector3 Camera::getLookFrom() const{
	return lookFrom;
}

Vector3 Camera::getLookAt() const{
	return lookAt;
}

Vector3 Camera::getViewUp() const{
	return viewUp;
}

float Camera::getFOV() const{
	return fov;
}

void Camera::setLookFrom(Vector3 lfp){
	lookFrom = lfp;
}
void Camera::setLookAt(Vector3 lap){
	lookAt = lap;
}
void Camera::setViewUp(Vector3 vup){
	viewUp = vup;
}
void Camera::setFOV(float fovAngle){
	fov = fovAngle;
}